#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
/*  
令牌桶算法
*/

#define BUFSIZE 10
#define BURST 100 //最多可以积攒的权限

static volatile int token = 0;

static void alrm_handler (int s)
{
    alarm(1);// 递归实现，自己给1s后的自己发信号
    token++;
    if(token > BURST)
        token = BURST;
}



int main (int argc, char **argv)
{
    int fd;
    char buf[BUFSIZE];

    int i;
    int iRet ,pos ,len;
    if(argc < 2) 
    {
        printf("Usage: %s<filename>\n", argv[0]);
        return -1;
    }

    /*
    以可读可写的方式打开文件，
    如果文件不存在则创建文件，
    */

    fd = open(argv[1], O_RDWR ,0666);
    if(fd == -1)
    {
        if(errno != ENOENT)
        {
            perror("open");//打印错误信息
            return -1;
        }

    }

    signal(SIGALRM , alrm_handler);
    alarm(1);


    while(1)
    {
    while(token <= 0)// 没有令牌时阻塞
        pause();

    token--;// 执行一次消耗一个令牌

    while ((len = read(fd , buf , BUFSIZE)) < 0)
    {
        if(errno == EINTR)
            continue;// 令牌桶算法，没有数据的时候每次信号到来也会攒下权限，当大量数据到来时，立刻处理完，权限用完恢复平常的速率。
        perror("read()");
        break;
    }

    if(len == 0)
        break;
    pos = 0;

    while(len > 0)
    {
        iRet = write(1 , buf+pos , len);
        if(iRet < 0)
        {
            if(errno == EINTR)
                continue;
            perror("write()");
            exit(1);
        }
        pos += iRet;
        len -= iRet;

    }
    
    }
    close(fd);//关闭
    return 0;
}